#include "shortestpath.h"
#include <iostream>
#include <cassert>
#include <algorithm>
#include <boost/program_options.hpp>

namespace po = boost::program_options;

po::options_description desc("Allowed options");
po::variables_map vm;

void process_options(int argc, char** argv);

int main(int argc, char** argv) 
{
  process_options(argc, argv);

  if (vm.count("help") || !vm.count("cost")) {
    std::cout << desc << "\n";
    return 0;
  }

  if (vm.count("gen")) {
    if (!vm.count("adjc")) {
      ShortestPathMatrix spm;
      spm.generate(vm["n"].as<int>(), vm["fe"].as<double>());
      spm.save(vm["cost"].as<std::string>());
    }
    else {
      ShortestPathAdjacent spa;
      spa.generate(vm["n"].as<int>(), vm["fe"].as<double>());
      spa.save(vm["cost"].as<std::string>());
    }
    return 0;
  }

  int s, t;
  double cost;
  PrintVertex printvertex;
  std::cout << "Input s = "; std::cin >> s;
  std::cout << "Input t = "; std::cin >> t;
  if (!vm.count("adjc")) {
    ShortestPathMatrix spm;
    spm.load(vm["cost"].as<std::string>());
    cost = spm(s, t);
    std::cout << "Distance[" << s << " --> " << t << "] = " << cost << "\n";
    std::cout << "Path = ";
    std::for_each(spm.path_.begin(), spm.path_.end(), printvertex);
    std::cout << "\n";
  }
  else {
    ShortestPathAdjacent spa;
    spa.load(vm["cost"].as<std::string>());
    cost = spa(s, t);
    std::cout << "Distance[" << s << " --> " << t << "] = " << cost << "\n";
    std::cout << "Path = ";
    std::for_each(spa.path_.begin(), spa.path_.end(), printvertex);
    std::cout << "\n";
  }
  return 0;
}

void process_options(int argc, char** argv) 
{
  desc.add_options()
    ("help", "produce this usage")
    ("cost", po::value<std::string>(), "file contains cost matrix")
    ("gen", "generate random data")
    ("adjc", "use adjacent representation")
    ("fe", po::value<double>()->default_value(0.5), "fraction of edges")
    ("n", po::value<int>()->default_value(10), "number of vertices")
    ;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);
}
